`timescale 1ns/1ns
module L9_data_rec_02(
		input	wire		resetb,
		input	wire		sclk,

		//网口配置总线
		input	wire		set_d_ok,
		input	wire	[15:0]	set_addr,
		input	wire	[7:0]	set_data,
	
		//当前端口范围
		input	wire	[5:0]	device_port,
		input	wire	[12:0]	port_start,

		//模式控制
		input   wire            init_mode,
		input   wire            black,

		//多模块共用设置数据输出
		output  reg	[10:0]  h_total,
		output  reg	[10:0]  l_total,
		output	reg	[7:0]	no_vs_set,	
                
		//网口数据输入
		input	wire		mac_flag,
		input	wire	[7:0]	mac_data,
		input	wire	[1:0]	mac_vendor,//0:无效包 1：中庆UDP 2：YT 3:中庆长包
		input	wire		mac_error,
		
		//显示数据输出
		output	reg		vsout,
		output	reg		dsout,
		output	wire	[7:0]	dout,
		output	reg		h_start,
		output	reg	[10:0]	h_num,
		output	reg		l2048_mode,
		
		//显示设置数据输出
		output	reg	[7:0]	state,
		output	reg	[7:0]	state_2,
		output	reg	[1:0]	color_restore_type,
		output	reg	[7:0]	testmode,
		output	reg	[8:0]	cascade_light,
		output	reg	[5:0]	sys_port,
		
		//测试信号
		output	wire	[7:0]	tout
		);

/************************************************/
//		信号定义
/************************************************/
parameter  Preamble_OFFSET	= 51;
parameter  PACK_TYPE_FIRST	= 52 - Preamble_OFFSET;
parameter  PACK_DEPTH_FIRST	= 56 - Preamble_OFFSET;
parameter  HPACK_ADDR_START	= 58 - Preamble_OFFSET;
parameter  PACK_LENGTH_HIGH	= 63 - Preamble_OFFSET;
parameter  PACK_DATA_START	= 64 - Preamble_OFFSET;
parameter  SET_PACK_OFFSET	= PACK_DATA_START-2;

reg	[12:0]	h_offset_bin,l_offset_bin,h_total_bin,l_total_bin;
reg	[5:0]	display_num;
reg	[1:0]	pixel_mode;
reg		auto_display_pos,local_depth_en_t;
wire		color_restore_receiver;

reg	[10:0]	mac_count,set_count;
reg	[12:0]	h_offset,l_offset,h_end,l_end;
reg	[14:0]	d_offset,d_end;
reg		zdec_vsout,set_en_pre,data_en_pre,set_en;
reg	[3:0]	set_count_t;
reg	[12:0]	h_num_rec,h_count;
reg	[14:0]	d_num_rec,d_end_rec,h_d_max,d_count;
reg		d_flag;

reg	[6:0]	contrast_da;
reg		flag_da,flag_db;
reg	[7:0]	contrast_adj,contrast_d;
wire	[17:0]	contrast_db;

reg		d_start,dsout_t,h_start_t;
reg		end_flag,end_flag_t;

/************************************************/
//		参数设置
/************************************************/
always	@(posedge sclk or negedge resetb)
	if (resetb==0)
		begin
			h_offset_bin	<= 0;
			l_offset_bin	<= 0;
			h_total_bin	<= 8;
			l_total_bin	<= 1024;
			display_num	<= 0;
			pixel_mode	<= 0;
			auto_display_pos<= 0;
			color_restore_type<= 2'b00;
		end
	else if (set_d_ok==1)
		case (set_addr)
			16'h0100:	h_offset_bin[7:0]	<= set_data;
			16'h0101:	h_offset_bin[12:8]	<= set_data;
			16'h0102:	l_offset_bin[7:0]	<= set_data;
			16'h0103:	l_offset_bin[12:8]	<= set_data;
			16'h0104:	h_total_bin[7:0]	<= set_data;
			16'h0105:	h_total_bin[12:8]	<= set_data;          
			16'h0106:	l_total_bin[7:0]	<= set_data;
			16'h0107:	l_total_bin[12:8]	<= set_data;  
			16'h0108:	begin
			                if(set_data == 0)                 //与未加多屏功能的配置文件保持兼容
			                        display_num <= 0; 	
			                else 
			                	display_num <= set_data - 1;
			                end		     
			16'h1032:	color_restore_type<=set_data[1:0];
			16'h1040:	pixel_mode<=set_data[1:0];
			
			16'h1099:	auto_display_pos<=set_data[0];	//L9使用，位置自适应使能
		endcase

assign  color_restore_receiver = color_restore_type[1];

/************************************************/
//		数据包内字节计数
/************************************************/
always	@(posedge sclk)
	if (mac_flag==0)
		mac_count<=0;
	else if (mac_count[10]==0)
		mac_count<=mac_count+1;
						
/************************************************/
//		自适应截取处理
/************************************************/
//选择自动确定截取位置/本地固化的街区位置
always	@(posedge sclk)
	if(auto_display_pos==1)
	begin
		h_offset	<= port_start;
		l_offset	<= 0;
		h_total		<= device_port;
		l_total		<= 1024;
	end
	else
	begin
		h_offset	<=h_offset_bin;
		l_offset	<=l_offset_bin;
		h_total		<=h_total_bin;
		l_total		<=l_total_bin;	
	end

always	@(posedge sclk)
	if (l_total > 1024)
		l2048_mode <= 1;
	else
		l2048_mode <= 0;
		
//行截取范围
always	@(posedge sclk)
	h_end <= h_offset + h_total;

//行内数据截取范围
always	@(posedge sclk)
	l_end <= l_offset + l_total;	

always@(posedge sclk)
	begin
		d_offset <= {l_offset[10:0],1'b0} + l_offset;
		d_end <= {l_end[10:0],1'b0} + l_end;
	end

/************************************************/
//		帧包处理
/************************************************/
always	@(posedge sclk)
	if (mac_flag==0)
		zdec_vsout<=0;
	else if (mac_count==PACK_TYPE_FIRST && mac_data==8'hFA && (mac_vendor==1 || mac_vendor==3))
		zdec_vsout<=1;

/************************************************/
//		即时显示设置参数提取
/************************************************/
//显示设置包标志
always	@(posedge sclk)
	if (mac_flag==0)
		set_en_pre<=0;
	else if (mac_count==PACK_TYPE_FIRST && mac_data==8'hF0 && (mac_vendor==1 || mac_vendor==3))
		set_en_pre<=1;

//设置数据计数
always@(posedge sclk)
	set_count<=mac_count-SET_PACK_OFFSET;

//判断是否是本显示屏数据
always@(posedge sclk)
        if(set_count[10:4]==display_num)
                set_en<=1'b1;
        else
                set_en<=1'b0;

always@(posedge sclk)
        set_count_t<=set_count[3:0];

//设置数据提取                
always	@(posedge sclk or negedge resetb)
	if (resetb==0)
		begin
			state		<=64;
			state_2		<=0;
			contrast_adj	<=64;
			cascade_light	<=9'h100;
			sys_port	<=0;
			testmode	<=0;
		end
	else if (set_en_pre==1 && set_en==1) begin
		case (set_count_t[3:0])
			0:	state		<= mac_data;
			1:	state_2		<= mac_data;
			3:	begin
			        if (mac_data!=0) 
					contrast_adj	<=mac_data;
				else
				        contrast_adj    <=64;        
				end
			4:	begin
				if(mac_data == 0)
					cascade_light <= 0;
				else
					cascade_light <= mac_data + 1;
				end
			14:	sys_port	<= mac_data;
			15:	testmode	<= mac_data;
		endcase
	end
	
/************************************************/
//	显示数据包解析本地行号，总列号计算
/************************************************/
//显示设置包标志
always	@(posedge sclk)
	if (mac_flag==0)
		data_en_pre<=0;
	else if (mac_count==PACK_TYPE_FIRST && mac_data==8'hF5 && (mac_vendor==1 || mac_vendor==3))	//UDP
		data_en_pre<=1;
		
//起始行号，每行数据长度
always	@(posedge sclk or negedge resetb)
	if(!resetb)
	begin
		h_num_rec<=0;
		d_end_rec<=0;
	end
	else if (data_en_pre==1)
		case (mac_count)
			HPACK_ADDR_START:	h_num_rec[7:0]<=mac_data;
			HPACK_ADDR_START+1:	h_num_rec[12:8]<=mac_data;
			HPACK_ADDR_START+4:	d_end_rec[7:0]<=mac_data;
			HPACK_ADDR_START+5:	d_end_rec[14:8]<=mac_data;
		endcase

//数据偏移量
always	@(posedge sclk or negedge resetb)
	if(!resetb)
		d_num_rec<=0;
	else if (data_en_pre==1)
		case (mac_count)
			HPACK_ADDR_START+2:	d_num_rec[7:0] <= mac_data;
			HPACK_ADDR_START+3:	d_num_rec[14:8] <= mac_data;
			HPACK_ADDR_START+5:	
				if ((d_end_rec[7:0] == 8'h00) && (mac_data == 8'h00)) begin
					d_num_rec <= d_num_rec + {d_num_rec, 1'b0};
					end
		endcase

always@(posedge sclk)
	h_d_max <= d_end_rec - 1;

/************************************************/
//		本地输出
/************************************************/
//数据有效标志
always	@(posedge sclk)
	if (data_en_pre == 1 && mac_count == PACK_LENGTH_HIGH)
		d_start <= 1;
	else
		d_start <= 0;

always	@(posedge sclk)
	if (mac_flag==0)
		d_flag <= 0;
	else if (data_en_pre==1 && d_start == 1)
		d_flag <= 1;

//行内数据计数
always	@(posedge sclk)
	if(zdec_vsout == 1)
		d_count <= 0;
	else if (d_flag == 1 && d_count >= h_d_max)
		d_count <= 0;
	else if (d_start == 1)
		d_count <= d_num_rec;
	else if (d_flag == 1)
		d_count <= d_count + 1;
				
//行号计算
always@(posedge sclk)
	if(zdec_vsout == 1)
		h_count <= 0;
	else if (d_flag == 1 && d_count >= h_d_max)
		h_count <= h_count + 1;
	else if (d_start == 1)
		h_count <= h_num_rec;
		
always@(posedge sclk)
	if(d_flag == 0)
		dsout_t <= 0;
	else if (h_count < h_offset || h_count >= h_end)
		dsout_t <= 0;
	else if (d_count < d_offset || d_count >= d_end)
		dsout_t <= 0;
	else
		dsout_t <= 1;

always@(posedge sclk)
	if(d_flag == 0)
		h_start_t <= 0;
	else if (h_count < h_offset || h_count >= h_end)
		h_start_t <= 0;
	else if (d_count == d_offset)
		h_start_t <= 1;
	else
		h_start_t <= 0;

always@(posedge sclk)
	if(vsout == 1)
		end_flag <= 0;
	else if (h_count >= h_end)
		end_flag <= 1;

always@(posedge sclk)
	end_flag_t <= end_flag;

always@(posedge sclk)
	dsout <= dsout_t;

assign	dout = contrast_d;

always@(posedge sclk)
	vsout <= zdec_vsout;

always@(posedge sclk)
	if (h_start_t == 1)
		h_start <= 1;
	else if (end_flag_t == 0 && end_flag == 1)
		h_start <= 1;
	else
		h_start <= 0;

always@(posedge sclk)
	h_num <= h_count - h_offset;

/************************************************/
//		对比度调整
/************************************************/
always	@(posedge sclk)
	if (mac_data[7]==1)
		contrast_da<=mac_data[6:0];
	else
		contrast_da<=~mac_data[6:0];

always	@(posedge sclk) begin
	flag_da<=mac_data[7];
	flag_db<=flag_da;
	end
	           
L9_mult_9X9_sync	adjust_contrast (
	.clock ( sclk ),
	.dataa ( {1'b0,contrast_adj} ),
	.datab ( {2'h0,contrast_da} ),
	.result ( contrast_db )
	);

always	@(posedge sclk)
	if (dsout_t == 0)
		contrast_d <= 0;
	else if (flag_db==1) begin
		if (contrast_db[14:13]>0)
			contrast_d<=8'hff;
		else
			contrast_d<={1'b1,contrast_db[12:6]};
		end
	else if (contrast_db[14:13]>0)
		contrast_d<=8'h0;
	else
		contrast_d<={1'b0,~contrast_db[12:6]};

/************************************************/
//		调试信号
/************************************************/
assign	tout = 0;

endmodule		

